<?php
/**
 * [LICENCE]
 */

require_once 'Madoqua/Observer/Subject/Interface/Exception.php';

require_once 'Madoqua/Exception/Log.php';

require_once 'Madoqua/View/Helper/Error.php';

/**
 * Abstract exception class
 * @category   Madoqua
 * @package    Madoqua_Exception
 * @author     Graham Anderson - graham@andtech.eu
 * @copyright  Copyright (c) 2008
 */
abstract class Madoqua_Exception_Abstract extends Exception
implements Madoqua_Observer_Subject_Interface_Exception
{

    /**
     * Critical condition, needs immediate attention, log this
     */
    const CRITICAL = 1;

    /**
     * Fatal application error, non recoverable, log this
     */
    const ERROR    = 2;
    
    /**
     * Undesirable but recoverable condition, log this
     */
    const WARNING  = 3; 
    
    /**
     * Normal but significant condition, log @ dev discretion
     */
    const NOTICE   = 4;
    
    /**
     * User should be notified there was a problem
     */
    const USER     = 5;
    
    /**
     * For verbose exception/error handling, do NOT explicitly set this for
     * exceptions. If app state is toggled to 'development' in the config, all
     * madoqua exceptions will be set to this value.
     */
    const DEBUG    = 6; 
    
    
    /**
     * Registered exception observers
     * @var array
     */
    protected $_handlers = array();
    
    /**
     * Set the code & message
     * @param string $message
     * @param int $code
     * @todo add error display handling for non fatal errors
     */
    function __construct($message, $code = 0)
    {
        if(Madoqua_Application::inDevelopment()) {
            $code = self::DEBUG;
        }
        parent::__construct($message, $code);
        
        $this->register(new Madoqua_Exception_Log());
             //->register(new Madoqua_View_Helper_Error());
    }

    /**
     * Register an exception handler
     * @param Madoqua_Observer_Interface_Exception $observer
     * @param string $name
     * @return mixed|Madoqua_Exception_Abstract|false
     */
    public function register(Madoqua_Observer_Interface_Exception $observer, $name = null)
    {
        if ($name === null) {
            $name = get_class($observer);
        }
        
        if (array_key_exists($name, $this->_handlers)) {
            return false;
        }
        
        $this->_handlers[$name] = $observer;
        return $this;
    }

    /**
     * Remove an exception handler
     * @param Madoqua_Observer_Interface_Exception $observer
     * @param string $name
     * @return bool
     */
    public function delete(Madoqua_Observer_Interface_Exception $observer, $name = null)
    {
        if ($name === null) {
            $name = get_class($observer);
        }
        
        if (array_key_exists($name)) {
            unset($this->_handlers[$name]);
            return true;      
        }
        return false;
    }

    /**
     * Push the exception out for handling
     * @return void
     */
    public function notify()
    {
        foreach ($this->_handlers as $observer) {
            $observer->handle($this);
        }
    }
    
    /**
     * Proxy to notify
     * @return void
     */
    public function handle()
    {
        $this->notify();
    }
}